let ws
let username
let currentUser
let currentUserList = {}
let unreadMessages = {}

function init() {

    if (Notification && Notification.permission !== 'granted') {
        Notification.requestPermission(status => {
            if (Notification.permission !== status) {
                Notification.permission = status
            }
        })
    }
}

function renderUserList(users) {
    console.log('render userlist');

    let userFragment = document.createDocumentFragment()
    let chatFragment = document.createDocumentFragment()

    for (let i = 0, len = users.length; i < len; i++) {

        if (users[i].name in currentUserList) {
            console.log("in here")
            console.log("#userlist-" + users[i].name)
            console.log(users[i].status)
            $("#userlist-" + users[i].name).removeClass()
            $("#userlist-" + users[i].name).addClass(users[i].status)
            // $("#userlist-" + users[i].name + " img").removeClass()
            // $("#userlist-" + users[i].name + " img").addClass(users[i].status)
            continue
        }

        currentUserList[users[i].name] = users[i]

        if (users[i].name == username) {
            $("#user-info img").attr("src", users[i].logo)
            continue
        }

        //<img src="${users[i].logo}" class="${users[i].status}">
        $(userFragment).append(`
            <li id="userlist-${users[i].name}" class="${users[i].status}">
                <img class="logo" src="${users[i].logo}">
                <span>${users[i].name}</span>
                <span class="counter">0</span>
            </li>
        `)
        $(chatFragment).append(`
            <div class="chat-message" id="user-${users[i].name}"></div>
        `)
        
    }

    $("#user-list ul").append(userFragment)
    $('#chat-message').append(chatFragment)
}

function isSameContent(last, current) {

    // for text and icons
    if (current.indexOf('<img') == -1 || current.indexOf('<img src="data:') == -1) {
        console.log('last = ', last)
        console.log('current = ', current)
        if (current === last) {
            return true
        } else {
            return false
        }
    } else {
        return false
    }
}

function renderChatMessage(message, notice) {

    if (notice) {

        // Add notification

        let notice = new Notification('Message from ' + message.from, {
            icon: currentUserList[message.from].logo,
            body: message.message    
        })

        setTimeout(() => {
            notice.close()
        }, 5000)
    }

    if (message.from != currentUser) {
        console.log('others')
        let count = parseInt($("#userlist-" + message.from + " .counter").text())
        console.log(count)
        if (!(message.from in unreadMessages)) {
            unreadMessages[message.from] = []
        }
        unreadMessages[message.from].push(message)
        $("#userlist-" + message.from + " .counter").text(count+1)
        $("#userlist-" + message.from + " .counter").show()
        return
    }

    let lastMessage = $("#user-" + message.from + " .message").last().html()
    $("#user-" + message.from + " .plus-1").hide()
    if (isSameContent(lastMessage, message.message)) {
        $("#user-" + message.from).append(`
            <div class="send-by-other">
                <img class="logo" src="${currentUserList[message.from].logo}"/>
                <span class="message">${message.message}</span>
                <span class="plus-1">+1</span>
            </div>
        `)
        $(".plus-1").click(function (ev) {
            sendMessage($(this).parent().children('span.message').html())
        })
    } else {
        $("#user-" + message.from).append(`
            <div class="send-by-other">
                <img class="logo" src="${currentUserList[message.from].logo}"/>
                <span class="message">${message.message}</span>
            </div>
        `)
    }
    $("#user-" + message.from).scrollTop(9999)
    $(".chat-message img").click(function (ev) {
        let img = new Image()
        img.src = this.src
        $(img).css({ "width": img.width, "height": img.height })
        $("#img-preview").html(img)
        $("#img-preview").show()
    })
}

function renderUnreadChatMessage() {

    if (!(currentUser in unreadMessages)) return

    let messageFragment = document.createDocumentFragment()
    for (let i = 0, len = unreadMessages[currentUser].length; i < len; i++) {
        renderChatMessage(unreadMessages[currentUser][i]) 
    }
    delete unreadMessages[currentUser]
    $("#userlist-" + currentUser + " .counter").hide()
    $("#userlist-" + currentUser + " .counter").text('0')
}

function connectWS(username) {
    console.log('connect to websocket server')

    ws = new WebSocket("ws://192.168.1.187:3001")

    ws.onopen = () => {
        console.log('connection to server opened!')

        ws.send(JSON.stringify({
            "type": "Login",
            "username": username
        }))
    }

    ws.onmessage = (message) => {
        let o = JSON.parse(message.data)

        switch (o.type) {
            case 'UserList': 
                renderUserList(o.value)
                break
            case 'ChatMessage':
                renderChatMessage(o)
                break
            case 'Login':
                login(o.value)
                break
            default:
                console.log('invalid message')
        }
    }
}

function sendMessage(message) {

    let html = message || $("#send-message pre").html()

    if (html && html.length > 0) {

        let lastMessage = $("#user-" + currentUser + " .message").last().html()
        $("#user-" + currentUser + " .plus-1").hide()
        if (isSameContent(lastMessage, html)) {
            $("#user-" + currentUser).append(`
                <div class="send-by-self">
                    <span class="plus-1">+1</span>
                    <span class="message">${html}</span>
                    <img class="logo" src="${currentUserList[username].logo}"/>
                </div>
            `)
            $(".plus-1").click(function (ev) {
                sendMessage($(this).parent().children('span.message').html())
            })
        } else {
            $("#user-" + currentUser).append(`
                <div class="send-by-self">
                    <span class="message">${html}</span>
                    <img class="logo" src="${currentUserList[username].logo}"/>
                </div>
            `)
        }
        $("#user-" + currentUser).scrollTop(9999)

        ws.send(JSON.stringify({
            'type': 'ChatMessage',
            'from': username,
            'to': $("#chat-user").text(),
            'message': html
        }))

        message || $("#send-message pre").html('')

        $(".chat-message img").click(function (ev) {
            let img = new Image()
            img.src = this.src
            $(img).css({ "width": img.width, "height": img.height })
            $("#img-preview").html(img)
            $("#img-preview").show()
        })

    }
}

function login(value) {

    console.log(value);
    if (value == 'valid') {
        $("#login").hide()
        $("#login p").hide()
        $("#logined").show()
        $("#user-info span").text(username)
    } else {
        $("#login p").show()
        $("#login input").val('').focus()
    }
}

function attachEvent() {

    $("#login input").focus()

    $("#login button").click((ev) => {
        username = $("#login input").val()
        connectWS(username)
    })
    $("#login input").on('keyup', ev => {
        if (ev.keyCode === 13) {
            username = $("#login input").val()
            connectWS(username)
        }
    })


    $("#user-list").click((ev) => {

        // structure: li>img+span
        if (ev.target.nodeName === 'LI') {
            currentUser = $(ev.target).children('span').eq(0).text()
        } else if (ev.target.nodeName === 'IMG') {
            currentUser = $(ev.target).next().text()
        } else if (ev.target.nodeName === 'SPAN') {
            currentUser = $(ev.target).text()
        }

        $(".chat-message").hide()
        $("#chat-user").text(currentUser)
        $('#user-' + currentUser).show()
        renderUnreadChatMessage()
    
    })


    /**
     * send message by two means
     * 1) click the button to send the message;
     * 2) Ctrl+Enter to send the message
     */
    $("#send-message button").click(sendMessage)
    $("#send-message pre").on('keyup', ev => {
        if (ev.ctrlKey && ev.keyCode === 13) {
            sendMessage()
        }
    })

    $("#send-message .icono-smile").click(ev => {
        console.log($("#send-message .icons").css("display"))
        if ($("#send-message .icons").css("display") == "none") {
            $("#send-message .icons").show()
        } else {
            $("#send-message .icons").hide()
        }
    })
    
    $("#send-message .icons img").click(function() {
        $("#send-message .icons").hide()
        $("#send-message pre").append($(this).clone())

        // TODO: when focus() move mouse to the last
        $("#send-message pre").focus()
    })

    $("#img-preview").dblclick(function (ev) {
        $(this).hide()
    })

    document.querySelector("#send-message pre").addEventListener("paste", function (ev) {
        var clipboardData = ev.clipboardData,
            items, item, types;

        if (clipboardData) {

            items = clipboardData.items

            if (!items) return

            item = items[0]
            
            types = clipboardData.types || []

            for (var i = 0; i < types.length; i++) {
                if (types[i] === 'Files') {
                    item = items[i]
                    break
                }
            }

            if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
                imgReader(item)
            }
        }

        ev.preventDefault()
    })
}

$(window).ready(function () {

    init()
    attachEvent()

})
